﻿using InterviewAppPhone.Managers;
using InterviewAppPhone.QuizPhoneService;
using LibQuestionIsPhone.Enums;
using LibQuestionIsPhone.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Threading;

namespace InterviewAppPhone.ViewModels
{
    public class DomandeViewModel : INotifyPropertyChanged
    {
        private static Random rnd;

        public event EventHandler FinePartitaEvent;

        public event EventHandler InizioPartitaEvent;

        private DispatcherTimer timer { get; set; }

        private long _punteggio;

        public long Punteggio
        {
            get { return _punteggio; }
            set { _punteggio = value; }
        }

        private long _oldPunteggio;

        public long OldPunteggio
        {
            get { return _oldPunteggio; }
            set { _oldPunteggio = value; }
        }

        private int _oldMoltiplicatore = 1;
        public int OldMoltiplicatore
        {
            get { return _oldMoltiplicatore; }
            set { _oldMoltiplicatore = value; }
        }

        private int _moltiplicatore = 1;
        public int Moltiplicatore
        {
            get { return _moltiplicatore; }
            set { _moltiplicatore = value; }
        }

        public DomandeViewModel()
        {
            timer = new DispatcherTimer();
            Punteggio = 0;
            DataFlowObject.MaxMoltiplicatore = 1;
        }

        private TimeSpan _tempoScandeza { get; set; }
        public TimeSpan TempoScadenza
        {
            get { return _tempoScandeza; }
            set
            {
                _tempoScandeza = value;
                OnPropertyChanged("TempoScadenza");
            }
        }

        public bool IsCalculate
        {
            get { return !IsDataLoaded; }
        }

        public int NumMaxDomande { get; set; }

        private bool _esitoRisposta { get; set; }

        private bool EsitoRisposta
        {
            set
            {
                _esitoRisposta = value;
                OnPropertyChanged("TestoEsitoRisposta");
                OnPropertyChanged("BackgroundEsitoRisposta");
                OnPropertyChanged("TestoEsitoPunti");
                OnPropertyChanged("PuntiAggiunti");
                OnPropertyChanged("Punteggio");
                OnPropertyChanged("OldPunteggio");
                OnPropertyChanged("Moltiplicatore");
                OnPropertyChanged("OldMoltiplicatore");
            }
        }

        public string TestoEsitoRisposta
        {
            get { return (_esitoRisposta) ? "Corretto" : "Sbagliato"; }
        }

        public string BackgroundEsitoRisposta
        {
            get { return (_esitoRisposta) ? "#FF24B655" : "#FFE50404"; }
        }

        public string TestoEsitoPunti
        {
            get { return (_esitoRisposta) ? "Guadagnati" : "Persi"; }
        }

        public string PuntiAggiunti
        {
            get { return (_esitoRisposta) ? (DataFlowObject.Difficolta.Punteggio * OldMoltiplicatore).ToString() : string.Format(" - {0}", DataFlowObject.Difficolta.Punteggio / 2); }
        }

        public int IndexDomanda
        {
            get { return Index + 1; }
        }

        private bool _isDataLoaded { get; set; }

        public bool IsDataLoaded
        {
            get { return _isDataLoaded; }
            private set
            {
                _isDataLoaded = value;
                OnPropertyChanged("IsDataLoaded");
                OnPropertyChanged("IsCalculate");
            }
        }

        public ObservableCollection<SingolaDomanda> ListaDomande { get; set; }

        private int Index { get; set; }

        public SingolaDomanda DomandaAttuale { get; set; }
        private string _tipologiaTest;

        public string TipologiaTest
        {
            get { return _tipologiaTest; }
            set
            {
                _tipologiaTest = value;
                OnPropertyChanged("TipologiaTest");
            }
        }



        /// <summary>
        /// Crea e aggiunge alcuni oggetti ItemViewModel nella raccolta di elementi.
        /// </summary>
        public void LoadData()
        {
            QuizServiceClient client = new QuizServiceClient();
            client.GetAllQuestionarioPhoneCompleted += client_GetAllQuestionarioPhoneCompleted;

            client.GetAllQuestionarioPhoneAsync(new QuizPhoneService.GetAllQuestionarioRequest()
            {
                IdDifficolta = DataFlowObject.Difficolta.IDDifficolta,
                idTipologiaTest = DataFlowObject.TipologiaTest.IDTest
            });
        }

        private void client_GetAllQuestionarioPhoneCompleted(object sender, GetAllQuestionarioPhoneCompletedEventArgs e)
        {
            ListaDomande = new ObservableCollection<SingolaDomanda>();
            var response = e.Result;

            foreach (var item in response.Questionario.ListaDomande)
                item.PossibiliRisposte = FiltraAndMescolaRisposte(item.PossibiliRisposte.ToList(), 4);

            List<SingolaDomanda> listadomande =
                (from dom in response.Questionario.ListaDomande
                 select new SingolaDomanda()
                 {
                     IDDomanda = dom.IdDomanda,
                     IndexDomanda = response.Questionario.ListaDomande.IndexOf(dom) + 1,
                     MaxDomanda = response.Difficolta.NumMaxDomande,
                     TestoDomanda = dom.Domanda,
                     isCorretta = TypeRispostaDomanda.NonRisposta,
                     ElencoRisposte =
                     (from risp in dom.PossibiliRisposte
                      select new SingolaRisposta()
                      {
                          IDRisposta = risp.IdPossibileRisposta,
                          TestoRisposta = risp.DescrizioneRisposta,
                          IsCorretto = risp.IsCorretta,
                      }).ToList()
                 }).ToList();

            foreach (var item in listadomande)
                ListaDomande.Add(item);
            Index = 0;
            DomandaAttuale = ListaDomande[Index];
            NumMaxDomande = ListaDomande.Count;
            UpdateAllData();
            TipologiaTest = DataFlowObject.TipologiaTest.NomeTest;
            IsDataLoaded = true;
            TempoScadenza = new TimeSpan(0, DataFlowObject.Difficolta.TempoMaxDomande, 0);
            timer.Tick += timer_Tick;
            timer.Interval = new TimeSpan(0, 0, 1);
            if (InizioPartitaEvent != null)
                InizioPartitaEvent(null, null);
        }

        public static ObservableCollection<PossibiliRisposteService> FiltraAndMescolaRisposte(List<PossibiliRisposteService> lista, int numMaxRisposte)
        {
            if (rnd == null)
                rnd = new Random();
            var listafinale = new ObservableCollection<PossibiliRisposteService>();
            for (int i = 0; i < numMaxRisposte; i++)
            {
                var percentuale = rnd.NextDouble();
                PossibiliRisposteService retval = lista.Skip(Convert.ToInt32(percentuale * (lista.Count - 1))).Take(1).FirstOrDefault();
                if (!listafinale.Contains(retval))
                    listafinale.Add(retval);
                else
                    i--;
            }
            return listafinale;
        }

        public void RiprendiPartita()
        {
            timer.Start();
        }
        public void InizioPartita()
        {
            timer.Start();
        }

        void timer_Tick(object sender, EventArgs e)
        {
            if (TempoScadenza.TotalSeconds != 0)

                TempoScadenza = TempoScadenza.Subtract(new TimeSpan(0, 0, 1));
            else
            {
                timer.Stop();
                FinePartitaClick(null, null);
            }
        }

        public void ResetAllData()
        {
            this.Punteggio = 0;
            this.Index = 0;
            IsDataLoaded = false;
            this.Moltiplicatore = 1;

        }

        public void UpdateAllData()
        {
            OnPropertyChanged("DomandaAttuale");
            OnPropertyChanged("NumMaxDomande");
            OnPropertyChanged("IndexDomanda");
        }

        public async Task<bool> NextDomanda()
        {
            if (Index != ListaDomande.Count - 1)
            {
                Index++;
                DomandaAttuale = ListaDomande[Index];
                UpdateAllData();
                return await Task.FromResult(true);

            }
            else
            {
                 FinePartitaClick(null, null);
                return await Task.FromResult(false);
            }
        }

        public async void FinePartita()
        {
            var manager = new MPunteggi();

            await manager.InviaPunteggio("Alessio Maugeri", Punteggio);
        }


        public void SetDataRisposta(SingolaRisposta sRisposta)
        {
            timer.Stop();
            OldPunteggio = Punteggio;
            OldMoltiplicatore = Moltiplicatore;
            Moltiplicatore = (sRisposta.IsCorretto) ? Moltiplicatore + 1 : 1;
            DataFlowObject.MaxMoltiplicatore = (Moltiplicatore > DataFlowObject.MaxMoltiplicatore) ? Moltiplicatore : DataFlowObject.MaxMoltiplicatore;
            Punteggio = (sRisposta.IsCorretto) ? _punteggio + (DataFlowObject.Difficolta.Punteggio * OldMoltiplicatore) : _punteggio - (DataFlowObject.Difficolta.Punteggio / 2);
            EsitoRisposta = sRisposta.IsCorretto;
        }

        protected  void FinePartitaClick(object sender, EventArgs e)
        {
            //espongo al chiamate l'azione richiesta sull'oggetto
            if (FinePartitaEvent != null)
                FinePartitaEvent(sender, e);
        }


        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(name));
        }

    }
}
